﻿#pragma once
#include <nlohmann/json.hpp>
#include <WinSock2.h>
#include <array>
#include <unordered_map>

class Config
{
public:
	Config();
	~Config();
	bool save();
	std::unordered_map<unsigned int, std::string>& DataTypes() { return data_types; }
	void chg() { has_changed = true; }
private:
	bool has_changed;
	std::unordered_map<unsigned int, std::string> data_types;
};

constexpr const char* ip_item_map[] = {
	"0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55","56","57","58","59","60","61","62","63","64","65","66","67","68","69","70","71","72","73","74","75","76","77","78","79","80","81","82","83","84","85","86","87","88","89","90","91","92","93","94","95","96","97","98","99","100","101","102","103","104","105","106","107","108","109","110","111","112","113","114","115","116","117","118","119","120","121","122","123","124","125","126","127","128","129","130","131","132","133","134","135","136","137","138","139","140","141","142","143","144","145","146","147","148","149","150","151","152","153","154","155","156","157","158","159","160","161","162","163","164","165","166","167","168","169","170","171","172","173","174","175","176","177","178","179","180","181","182","183","184","185","186","187","188","189","190","191","192","193","194","195","196","197","198","199","200","201","202","203","204","205","206","207","208","209","210","211","212","213","214","215","216","217","218","219","220","221","222","223","224","225","226","227","228","229","230","231","232","233","234","235","236","237","238","239","240","241","242","243","244","245","246","247","248","249","250","251","252","253","254","255"
};

enum CHANNEL_PROTO_TYPE
{
	CHANNEL_PROTO_TYPE_TCP_SERVER = 0x0001,
	CHANNEL_PROTO_TYPE_TCP_CLIENT = 0x0002,
	CHANNEL_PROTO_TYPE_UDP =  0x0004,
	CHANNEL_PROTO_TYPE_FILE = 0x0008,
	CHANNEL_PROTO_TYPE_MAX
};

enum CHANNEL_STATE
{
	CHANNEL_STATE_START,
	CHANNEL_STATE_UNSTART,
	CHANNEL_STATE_CONNECTED,
	CHANNEL_STATE_CONNECTING,
	CHANNEL_STATE_UNCONNECT,
	CHANNEL_STATE_TIMEOUT,
	CHANNEL_STATE_MAX,
};

union addr_convert
{
	char b[4];
	long s;
	constexpr addr_convert(long _s) :s{ _s } {}
};

inline bool check_ip(const char* ip)
{
	return inet_addr(ip) != INADDR_NONE;
}

struct SocketAddress
{
	sockaddr_in addr;
	sockaddr* get() 
	{
		return (sockaddr*)&addr; 
	}
	int len() { return sizeof(sockaddr_in); }
	std::array<char, 16> ip;
	USHORT port;
	
	bool valid()
	{
		return addr.sin_family != 0;
	}

	bool init(const char* ip_str, USHORT p)
	{
		ip.fill(0);
		memcpy(ip.data(), ip_str, 15);
		port = p;

		addr.sin_family = AF_INET;
		addr.sin_addr.S_un.S_addr = inet_addr(ip.data());
		addr.sin_port = htons(port);
		
		bool res = addr.sin_addr.S_un.S_addr != INADDR_NONE;
		return res;
	}

	bool init_server(long addr_ip, USHORT p)
	{
		ip.fill(0);
		port = p;

		addr.sin_family = AF_INET;
		addr.sin_addr.S_un.S_addr = addr_ip;
		addr.sin_port = htons(port);

		{
			std::string res_str{ inet_ntoa(addr.sin_addr) };

			assert(res_str.size() < 16);

			memcpy(ip.data(), res_str.data(), 15);
		}

		bool res = addr.sin_addr.S_un.S_addr != INADDR_NONE;
		return res;
	}

	bool init_client(USHORT p)
	{
		ip.fill(0);
		strcpy(ip.data(), "0.0.0.0");
		port = p;

		addr.sin_family = AF_INET;
		addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
		addr.sin_port = htons(port);

		bool res = addr.sin_addr.S_un.S_addr != INADDR_NONE;
		return res;
	}

	void sync()
	{
		port = ntohs(addr.sin_port);
		ip.fill(0);
		strcpy(ip.data(), inet_ntoa(addr.sin_addr));
	}
};

constexpr UINT channel_udp_max{ 64u };

struct UDP_INFO
{
	/// <summary>
	/// 地址
	/// </summary>
	SocketAddress address;
	/// <summary>
	/// 备注
	/// </summary>
	char notes[64];
	/// <summary>
	/// 数据类型
	/// </summary>
	UINT data_type;
};

struct ChannelCreateInfo
{
	/// <summary>
	/// 类型
	/// </summary>
	UINT32 type;
	/// <summary>
	/// 输入端地址
	/// </summary>
	SocketAddress input_address;
	/// <summary>
	/// 输出端地址，针对TCP客户端，服务端用这个当local地址
	/// </summary>
	SocketAddress output_address;
	/// <summary>
	/// UDP发送地址list
	/// </summary>
	std::vector<UDP_INFO> upd_address;
	/// <summary>
	/// UI上的通道标题
	/// </summary>
	char title[MAX_PATH];
	/// <summary>
	/// 输入通道类型，另见Config
	/// </summary>
	UINT input_type;
	/// <summary>
	/// 输出通道类型，另见Config
	/// </summary>
	UINT output_type;
	/// <summary>
	/// 针对文件通道，源文件目录
	/// </summary>
	char src_path[MAX_PATH];
	/// <summary>
	/// 针对文件通道，目标目录
	/// </summary>
	char dst_path[MAX_PATH];
	/// <summary>
	/// 文件通道接受数据时，保存的文件后缀
	/// </summary>
	char suffix_name[16];
};

constexpr int max_cache_size{ 8192 };

struct read_buffer_cache
{
	size_t size;
	unsigned int data_type;
	std::array<char, max_cache_size> data;
};

struct DataBufferBase
{
	virtual void* data() = 0;
	virtual void free() = 0;
	int len;
};